/* global Cesium viewer */
import shp from 'shpjs';
import { antiShake } from 'U/serviceOptimize';

let datasourceData = '';
class DrawObj {
    constructor(callFunc) {
        this.callFunc = callFunc ? callFunc : null;
        this.drawHelper = new Cesium.C_DrawHelper(viewer.scene);
    }
    // 绘制矩形
    drawExtent() {
        this.clearDataSource();
        this.drawHelper.enable = true;
        this.drawHelper.startDrawingExtent(
            {
                fill: true,
                outline: true,
                outlineColor: 'rgba(253, 128, 69, 1.0)',
                outlineWidth: 3,
                material: Cesium.Color.fromCssColorString('rgba(253, 128, 69, 1.0)'),
                enEdit: false,
            },
            {
                startCallback: this.drawStartCallback.bind(this),
                endCallback: this.drawEndCallback.bind(this),
            }
        );
    }
    //  绘制圆
    drawCircle() {
        this.clearDataSource();
        this.drawHelper.enable = true;
        this.drawHelper.startDrawingCircle(
            {
                fill: false,
                outline: true,
                outlineColor: 'rgba(253, 128, 69, 1.0)',
                outlineWidth: 3,
                enEdit: false,
            },
            {
                startCallback: this.drawStartCallback.bind(this),
                endCallback: this.drawEndCallback.bind(this),
            }
        );
    }
    // 绘制点
    drawPoint() {
        this.funa();
    }
    funa() {
        this.clearDataSource();
        this.drawHelper.stopMarkerFun(false);
        this.drawHelper.enable = true;
        this.drawHelper.startDrawingMarker(
            {},
            {
                startCallback: this.drawStartCallback.bind(this),
                endCallback: this.drawEndCallback.bind(this),
            }
        );
    }
    ctrlFunClick() {
        antiShake(this.funa.bind(this), 1000)();
    }

    // 绘制面
    drawArea() {
        this.clearDataSource();
        this.drawHelper.enable = true;
        this.drawHelper.startDrawingPolygon(
            {
                fill: true,
                outline: true,
                material: Cesium.Color.fromCssColorString('rgba(253, 128, 69, 1.0)'),
                outlineColor: 'rgba(253, 128, 69, 1.0)',
                outlineWidth: 3,
                enEdit: false,
            },
            {
                startCallback: this.drawStartCallback.bind(this),
                endCallback: this.drawEndCallback.bind(this),
            }
        );
    }
    // 解析shape文件
    parsingShape(files, fileList) {
        let _self = this;
        this.drawHelper.stopDrawing();
        this.drawHelper.clearMarker();
        if (fileList) {
            let file = fileList[fileList.length - 1];
            const name = file.name;
            const extension = name.split('.')[1];
            if ('zip' !== extension) {
                this.$message.warning('文件不是zip文件！请重新选择文件');
            } else {
                const reader = new FileReader();
                const fileData = file.raw;
                reader.readAsArrayBuffer(fileData);
                reader.onload = function(e) {
                    shp(e.target.result)
                        .then(function(data) {
                            _self.createAdministrativeDivisions({
                                jsonObject: data,
                            });
                        })
                        .catch(function() {
                            _self.$message.warning('文件不符合空间数据规范！请重新选择文件');
                        });
                };
            }
        }
    }
    // 合并geojson的范围坐标为一个数组
    mergeArr(data) {
        let arr = [];
        data.features.forEach(item => {
            let tempArr = [];
            if (item.geometry.bbox) {
                tempArr.push({
                    lon: item.geometry.bbox[0],
                    lat: item.geometry.bbox[1],
                });
                tempArr.push({
                    lon: item.geometry.bbox[2],
                    lat: item.geometry.bbox[3],
                });
                arr = arr.concat(tempArr);
            } else if (item.geometry.coordinates) {
                for (let i = 0; i < item.geometry.coordinates.length; i++) {
                    for (let j = 0; j < item.geometry.coordinates[i].length; j++) {
                        for (let k = 0; k < item.geometry.coordinates[i][j].length; k++) {
                            tempArr.push({
                                lon: item.geometry.coordinates[i][j][k][0],
                                lat: item.geometry.coordinates[i][j][k][1],
                            });
                        }
                    }
                }
                arr = arr.concat(tempArr);
            }
        });
        return arr;
    }
    // 创建geojson格式数据
    createAdministrativeDivisions(data, showPolygon = true) {
        this.deleteArea(true);
        if (!data) return;
        let geo = data.jsonObject;
        localStorage.setItem('shapData', JSON.stringify(geo));
        let thematicRange = this.getRange(this.mergeArr(geo));
        this.callFunc && this.callFunc('', thematicRange);
        let entity = null;
        let color = Cesium.Color.fromCssColorString('rgba(253, 128, 69, 1.0)');
        Cesium.GeoJsonDataSource.load(geo).then(dataSource => {
            dataSource.name = 'specialProducts';
            for (let i = 0; i < dataSource.entities.values.length; ++i) {
                entity = dataSource.entities.values[i];
                if (!entity.polygon) continue;

                entity.polygon = new Cesium.PolygonGraphics({
                    arcType: Cesium.ArcType.RHUMB,
                    hierarchy: entity.polygon.hierarchy,
                    outline: false,
                    material: color.withAlpha(showPolygon ? 0.2 : 0),
                    classificationType: Cesium.ClassificationType.TERRAIN,
                });

                entity.polyline = new Cesium.PolylineGraphics({
                    positions: [
                        ...entity.polygon.hierarchy._value.positions,
                        entity.polygon.hierarchy._value.positions[0],
                    ],
                    width: 3,
                    material: color,
                    clampToGround: true,
                    classificationType: Cesium.ClassificationType.TERRAIN,
                    zIndex: 0,
                });
                let holes = entity.polygon.hierarchy._value.holes;
                for (let j = 0; j < holes.length; ++j) {
                    dataSource.entities.add({
                        polyline: {
                            positions: [...holes[j].positions, holes[j].positions[0]],
                            width: 3,
                            clampToGround: true,
                            material: color,
                            classificationType: Cesium.ClassificationType.TERRAIN,
                            zIndex: 0,
                        },
                    });
                }
            }
            viewer.dataSources.add(dataSource);
            viewer.zoomTo(dataSource, new Cesium.HeadingPitchRange(0, -Math.PI / 2, 0));
            datasourceData = dataSource;
        });
    }
    // 创建绘制面结束后的面（为了控制面能够清除）
    createTarget(positions, radius) {
        let pois = positions.map(item => {
            return {
                x: item.x,
                y: item.y,
                z: item.z,
            };
        });
        let obj = {
            pois: JSON.stringify(pois),
            radius,
        };
        localStorage.setItem('drawPositions', JSON.stringify(obj));
        let entity = viewer.entities.add({
            id: 'drawArea',
            polyline: {
                positions: positions,
                arcType: Cesium.ArcType.RHUMB,
                width: 3,
                outlineColor: Cesium.Color.fromCssColorString('rgba(253, 128, 69, 1.0)'),
                material: Cesium.Color.fromCssColorString('rgba(253, 128, 69, 1.0)'),
                clampToGround: true,
                classificationType: Cesium.ClassificationType.TERRAIN,
                distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, radius * 300),
            },
            polygon: {
                hierarchy: positions,
                arcType: Cesium.ArcType.RHUMB,
                fill: true,
                outline: true,
                outlineWidth: 13,
                outlineColor: Cesium.Color.fromCssColorString('rgba(253, 128, 169, 1.0)'),
                material: Cesium.Color.fromCssColorString('rgba(253, 128, 69, .5)'),
                clampToGround: true,
                classificationType: Cesium.ClassificationType.TERRAIN,
                distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, radius * 300),
            },
        });
        return entity;
    }
    changeMaterial(alpha) {
        let entity = viewer.entities.getById('drawArea');
        if (entity) {
            entity.polygon.material = Cesium.Color.fromCssColorString(
                `rgba(253, 128, 69,${alpha})`
            );
        }
    }
    // 清空绘制的geojson面
    clearDataSource() {
        if (datasourceData) {
            localStorage.setItem('shapData', '');
            viewer.dataSources.remove(datasourceData);
            datasourceData = '';
        }
    }
    clearMarker() {
        this.drawHelper.clearMarker();
    }
    // 清空绘制
    deleteArea(flag) {
        localStorage.setItem('drawPositions', '');
        this.drawHelper.clearMarker();
        viewer.entities.removeById('drawArea');
        this.clearDataSource();
        if (flag) {
            this.drawHelper.stopDrawing();
        }
    }
    // 获取专题图范围
    getRange(arr) {
        let arr1 = arr.map(item => {
            return item.lon;
        });
        let arr2 = arr.map(item => {
            return item.lat;
        });
        let minx = Math.min(...arr1);
        let miny = Math.min(...arr2);
        let maxx = Math.max(...arr1);
        let maxy = Math.max(...arr2);

        let points = [
            Cesium.Cartesian3.fromDegrees(maxx, miny, 0),
            Cesium.Cartesian3.fromDegrees(minx, maxy, 0),
        ];
        return { points, xvalue: maxx - minx, yvalue: maxy - miny };
    }
    // 坐标转换
    toLonLat(poi) {
        let ellipsoid = viewer.scene.globe.ellipsoid;
        let cartographic = ellipsoid.cartesianToCartographic(poi);
        let lat = Cesium.Math.toDegrees(cartographic.latitude);
        let lon = Cesium.Math.toDegrees(cartographic.longitude);
        return { lat, lon };
    }
    getPoiArr(pois) {
        const arr = pois.map(element => {
            return this.toLonLat(element);
        });
        return arr;
    }
    // 绘制图形结束的回调
    drawEndCallback(primitive, primitives, positions) {
        if (!primitive) {
            return;
        }
        // this.callFunc && this.callFunc(primitive,positions);
        if (primitive.getType() === 'Marker') {
            let lon = primitive.position.lon;
            let lat = primitive.position.lat;
            this.callFunc && this.callFunc(primitive, '', `POINT(${lon} ${lat})`);
            primitive.id = 'drawMarker';
            this.ctrlFunClick();
        } else {
            let degreesArr = primitive.getDegreesBoundary();
            let degrees = this.positionsHandler(degreesArr);
            positions = primitive.getBoundary();
            let thematicRange = this.getRange(this.getPoiArr(positions));
            this.callFunc && this.callFunc(primitive, thematicRange, degrees[0]);
            let boundingSphere = Cesium.BoundingSphere.fromPoints(positions);
            this.createTarget([...positions, positions[0]], boundingSphere.radius);
            primitive.destroy();
            primitive.getType() === 'GroundPolygon' ? this.drawArea() : this.drawExtent();
        }
    }
    positionsHandler(positions) {
        let bool = false;
        for (let i = 1; i < positions.length; ++i) {
            if (Math.abs(positions[i].longitude - positions[i - 1].longitude) > 180) {
                bool = true;
                break;
            }
        }
        if (bool) {
            let ps1 = '';
            let ps2 = '';
            let ps1Arr = [];
            let ps2Arr = [];
            for (let i = 0; i < positions.length; ++i) {
                if (positions[i].longitude > 0) {
                    ps1 += `${positions[i].longitude} ${positions[i].latitude},`;
                    ps2 += `${positions[i].longitude - 360} ${positions[i].latitude},`;
                    ps1Arr.push(positions[i]);
                    ps2Arr.push({
                        longitude: positions[i].longitude - 360,
                        latitude: positions[i].latitude,
                    });
                } else {
                    ps1Arr.push({
                        longitude: positions[i].longitude + 360,
                        latitude: positions[i].latitude,
                    });
                    ps2Arr.push(positions[i]);
                    ps1 += `${positions[i].longitude + 360} ${positions[i].latitude},`;
                    ps2 += `${positions[i].longitude} ${positions[i].latitude},`;
                }
            }
            if (positions[0].longitude > 0) {
                ps1 += `${positions[0].longitude} ${positions[0].latitude}`;
                ps2 += `${positions[0].longitude - 360} ${positions[0].latitude}`;
            } else {
                ps1 += `${positions[0].longitude + 360} ${positions[0].latitude}`;
                ps2 += `${positions[0].longitude} ${positions[0].latitude}`;
            }
            let multiPolygon = `MultiPolygon(((${ps1})),((${ps2})))`;
            return [multiPolygon, [ps1Arr, ps2Arr]];
        }

        let polygon = 'POLYGON((';
        for (let i = 0; i < positions.length; i++) {
            polygon += `${positions[i].longitude} ${positions[i].latitude},`;
        }
        polygon += `${positions[0].longitude} ${positions[0].latitude}))`;
        return [polygon];
    }
    drawStartCallback() {
        this.drawHelper.stopMarkerFun(false);
        viewer.entities.removeById('drawArea');
        localStorage.setItem('drawPositions', '');
    }
}
export default DrawObj;
